/*
 * main.cpp
 *
 *  Created on: 28.10.2013
 *      Author: ulgish
 */
#include <iostream>
#include <string>
#include <cstdlib>
#include <lab1/Lab1.h>
#include <lab2/Lab2.h>
#include <lab3/Lab3.h>
#include <lab4/Lab4.h>
#include <lab5/client/Client.h>
#include <lab5/server/Server.h>
#define STD(A) using std::A;
#define D(A) using DT::A;
STD(cin)
STD(cout)
STD(endl)
STD(string)
STD(getline)
STD(exit)
D(writer)
#define CHANNEL "mychannel"

#define WRITE_HEAD\
		cout << "SPbETU \"LETI\"\n\tFakultet KTI\n\tGroup 9362\n\tEgorov V.T.";\
		cout << "\n\n\tReal Time System\n";\
		cout << "\n\nLaboratory work 1:\n\tjust creating some threads.\n";\
		cout << "\n\nLaboratory work 2:\n\tthe problem of limited buffer.\n";\
		cout << "\n\nLaboratory work 3:\n\tDining philosophers problem.\n";\
		cout << "\n\nLaboratory work 4:\n\tMessage passing in QNX.\n";
#define WRITE_INVITE\
	cout << "Select the number of laboratory work: enter number from 1 to 4.\nIn other case programm will be exit.\nYours select:";

#define WRITE_INVITE_VARIABLE(name)\
		cout << "Enter " << name << ":\n";

#define WRITE_LAB_STARTED(a)\
		cout << "Laboratory work #" << (a) << " started.\n";

struct Lab2_prm{
	int storeSize;
	int consumerCount;
	int supplierCount;
};

#define lab2_run(prm) prm.storeSize, prm.consumerCount, prm.supplierCount

struct Lab3_prm{
	int countOfThinkers;
	bool isDanger;
	int timeOfModelingInSecond;
};


int main(){
	Lab1* lab1;
	Lab2* lab2;
	Lab3* lab3;
	Lab4* lab4;
	Lab2_prm lab2_prm;
	Lab3_prm lab3_prm;
	Client* client;
	Server* server;
	WRITE_HEAD
	char cSelect;
	string temp;
	int child_id;
	bool end = false;
	do{
		WRITE_INVITE
		cin >> cSelect;
		switch(cSelect - 48){
		case 1:
			WRITE_LAB_STARTED(1);
			lab1 = new Lab1();
			lab1->go();
			delete lab1;
			break;
		case 2:
			WRITE_INVITE_VARIABLE("size of store");
			cin >> lab2_prm.storeSize;
			WRITE_INVITE_VARIABLE("consumer count");
			cin >> lab2_prm.consumerCount;
			WRITE_INVITE_VARIABLE("supplier count");
			cin >> lab2_prm.supplierCount;
			lab2 = new Lab2(lab2_run(lab2_prm));
			WRITE_LAB_STARTED(2);
			lab2->go();
			delete lab2;
			break;
		case 3:
			WRITE_INVITE_VARIABLE("count of thinkers");
			cin >> lab3_prm.countOfThinkers;
			lab3_prm.timeOfModelingInSecond = 0;
			getline(cin, temp, '\n');
			do{
				WRITE_INVITE_VARIABLE("this is dangerous run? (y/n)");
				getline(cin, temp, '\n');
				if (temp.length() > 0){
					if (temp[0] == 'y' || temp[0] == 'Y'){
						lab3_prm.timeOfModelingInSecond = 1;
						lab3_prm.isDanger = true;
					}else if(temp[0] == 'n' || temp[0] == 'N'){
						lab3_prm.timeOfModelingInSecond = -1;
						lab3_prm.isDanger = false;
					}else{
						cout << "Incorrect letter!!!\n";
					}
				}
			}while(lab3_prm.timeOfModelingInSecond == 0);
			WRITE_INVITE_VARIABLE("time of modeling (in seconds)");
			cin >> lab3_prm.timeOfModelingInSecond;
			lab3 = new Lab3(lab3_prm.countOfThinkers);
			WRITE_LAB_STARTED(3)
			if (lab3_prm.isDanger){
				lab3->goDanger(lab3_prm.timeOfModelingInSecond);
			}else{
				lab3->goSafely(lab3_prm.timeOfModelingInSecond);
			}
			break;
		case 4:
			WRITE_LAB_STARTED(4)
			cout.flush();

			if (fork() == 0){
				//child, client
				sleep(1);
				client = new Client(string(CHANNEL));
				getline(cin, temp, '\n');
				do{
					WRITE_INVITE_VARIABLE("message for server");
					getline(cin, temp, '\n');
					client->sendMsg(temp);
					if (temp.compare("exit") == 0){
						break;
					}
				}while(true);

				delete client;
				exit(1);
			}else{
				//parent, server
				server = new Server(string(CHANNEL));
				server->start();
				sleep(1);
				delete server;
				//killing the Zombie ;-)
				wait(NULL);
			}
			break;
		default:
			end = true;
			break;
		}
	}while(!end);
	//new Lab1().go();
//	Lab1 lab1;
//	lab1.go();
//	Lab2 lab2(20, 21, 40);
//	lab2.go();
//	Lab3 lab3(10, 5, 15);
//	lab3.goSafely(35);
//	lab3.goDanger(5);
//	Lab4 lab4(5, 1, 2, 10);
//	lab4.go(60);

	return 0;
}

